!
!    date class
!
!-------------------------------------------------------------------------
!BOP
!
! !IROUTINE:  date_set_calendar
!                            
! 
! !INTERFACE:
!
      subroutine date_set_calendar ( type )

! !USES:
!
!     none

! !INPUT PARAMETERS: 
!
      implicit NONE

      integer, intent(in) :: type           ! Calendar type (e.g. NO_LEAP)

! !OUTPUT PARAMETERS:
!
!      none

! !DESCRIPTION:
!
! Specifies the calendar to be used in date calculations.  Valid values
! of {\tt type} are given by the integer parameters that identify calendars.
!
! !REVISION HISTORY: 
!
!  Feb 8, 2001    B. Eaton   Specification.
!
!EOP
!-------------------------------------------------------------------------

!BOP
!
! !IROUTINE:  date_set
! 
! !INTERFACE:
!
      function date_set ( yearmmdd, tod )

! !USES:

!     none

! !INPUT PARAMETERS: 
!
      implicit NONE

      integer, intent(in) :: yearmmdd       ! Date
      integer, intent(in), optional :: tod  ! Time of day

! !OUTPUT PARAMETERS:
!
      type(date_t) :: set_date              ! Returned date

! !DESCRIPTION:
!
! Returns the date specified by {\tt yearmmdd} and optionally {\tt tod}.  
! If {\tt tod} is not specified then 0Z is assumed.
!
! !REVISION HISTORY: 
!
!  Feb 8, 2001    B. Eaton   Specification.
!
!EOP
!-------------------------------------------------------------------------

!BOP
!
! !IROUTINE:  date_get
! 
! !INTERFACE:
!
      subroutine date_get ( date, yearmmdd, tod )

! !USES:

!     none

! !INPUT PARAMETERS: 
!
      implicit NONE

      type(date_t), intent(in) :: date      ! Input date

! !OUTPUT PARAMETERS:
!
      integer, intent(out) :: yearmmdd      ! Returned date
      integer, intent(out) :: tod           ! Returned time of day

! !DESCRIPTION:
!
! Returns the attributes of {\tt date} in the form of {\tt yearmmdd}
! and {\tt tod}.  
!
! !REVISION HISTORY: 
!
!  Feb 8, 2001    B. Eaton   Specification.
!
!EOP
!-------------------------------------------------------------------------

!BOP
!
! !IROUTINE:  date_to_str
! 
! !INTERFACE:
!
      function date_to_str ( date )

! !USES: 

!     none

! !INPUT PARAMETERS: 
!
      implicit NONE

      type(date_t), intent(in) :: date      ! Input date

! !OUTPUT PARAMETERS:
!
      character (len=32) :: date_to_str     ! Returned string

! !DESCRIPTION:
!
! Returns {\tt} date in a string with the format "year-mm-dd hh:mm:ss".
!
! !REVISION HISTORY: 
!
!  Feb 8, 2001    B. Eaton   Specification.
!
!EOP
!-------------------------------------------------------------------------

!BOP
!
! !IROUTINE:  date_increment
! 
! !INTERFACE:
!
      function date_increment ( date, time )

! !USES: 

!     none

! !INPUT PARAMETERS: 
!
      implicit NONE

      type(date_t), intent(in) :: date      ! Initial date
      type(time_t), intent(in) :: time      ! Time increment

! !OUTPUT PARAMETERS:
!
      type(date_t) :: date_increment        ! Returned date

! !DESCRIPTION:
!
! Increments a {\tt date} by a {\tt time} and returns the
! new value of {\tt date}.
!
! !REVISION HISTORY: 
!
!  Feb 8, 2001    B. Eaton   Specification.
!
!EOP
!-------------------------------------------------------------------------

!BOP
!
! !IROUTINE:  date_increment_sec
! 
! !INTERFACE:
!
      function date_increment_sec ( date, nsec )

! !USES: 

!     none

! !INPUT PARAMETERS: 
!
      implicit NONE

      type(date_t), intent(in) :: date      ! Initial date
      integer, intent(in) :: nsec           ! Time increment in seconds

! !OUTPUT PARAMETERS:
!
      type(date_t) :: date_increment_sec    ! Returned date

! !DESCRIPTION:
!
! Increments a {\tt date} by {\tt nsec} and returns the
! new value of {\tt date}.
!
! !REVISION HISTORY: 
!
!  Feb 8, 2001    B. Eaton   Specification.
!
!EOP
!-------------------------------------------------------------------------

!BOP
!
! !IROUTINE:  date_increment_day
! 
! !INTERFACE:
!
      function date_increment_day ( date, nday )

! !USES: 

!     none

! !INPUT PARAMETERS: 
!
      implicit NONE

      type(date_t), intent(in) :: date      ! Initial date
      integer, intent(in) :: nday           ! Time increment in days

! !OUTPUT PARAMETERS:
!
      type(date_t) :: date_increment        ! Returned date

! !DESCRIPTION:
!
! Increments a {\tt date} by {\tt nday} and returns the
! new value of {\tt date}.
!
! !REVISION HISTORY: 
!
!  Feb 8, 2001    B. Eaton   Specification.
!
!EOP
!-------------------------------------------------------------------------

!BOP
!
! !IROUTINE:  date_increment_month
! 
! !INTERFACE:
!
      function date_increment_month ( date, nmon )

! !USES: 

!     none

! !INPUT PARAMETERS: 
!
      implicit NONE

      type(date_t), intent(in) :: date      ! Initial date
      integer, intent(in) :: nmon           ! Time increment in months

! !OUTPUT PARAMETERS:
!
      type(date_t) :: date_increment        ! Returned date

! !DESCRIPTION:
!
! Increments a {\tt date} by {\tt nmon} and returns the
! new value of {\tt date}.
!
! Incrementing a date by months only changes the year and month unless the 
! day of month in the final month doesn't exist. In this case the closest day 
! that does exist is used. E.g., 31 Jan 2000 + 1 month = 29 Feb 2000. But note 
! that 28 Feb 2001 + 1 month = 28 Mar 2001, i.e., end of month days are not 
! preserved by adding months.
!
! !REVISION HISTORY: 
!
!  Feb 8, 2001    B. Eaton   Specification.
!
!EOP
!-------------------------------------------------------------------------

!BOP
!
! !IROUTINE:  date_increment_year
! 
! !INTERFACE:
!
      function date_increment_year ( date, nyr )

! !USES: 

!     none

! !INPUT PARAMETERS: 
!
      implicit NONE

      type(date_t), intent(in) :: date      ! Initial date
      integer, intent(in) :: nyr            ! Time increment in years

! !OUTPUT PARAMETERS:
!
      type(date_t) :: date_increment_year   ! Returned date

! !DESCRIPTION:
!
! Increments a {\tt date} by {\tt nyr} and returns the
! new value of {\tt date}.
!
! Incrementing a date by years only changes the year, unless the initial 
! date falls on a day of the month that doesn't exist in the final year. In 
! this case the final month will remain unchanged and the final day of the 
! month will be the closest day that does exist: e.g., 29 Feb 2000 + 1 year 
! is 28 Feb 2001.
!
! !REVISION HISTORY: 
!
!  Feb 8, 2001    B. Eaton   Specification.
!
!EOP
!-------------------------------------------------------------------------

!BOP
!
! !IROUTINE:  date_decrement
! 
! !INTERFACE:
!
      function date_decrement ( date, time )

! !USES: 

!     none

! !INPUT PARAMETERS: 
!
      implicit NONE

      type(date_t), intent(in) :: date      ! Initial date
      type(time_t), intent(in) :: time      ! Time decrement

! !OUTPUT PARAMETERS:
!
      type(date_t) :: date_increment        ! Returned date

! !DESCRIPTION:
!
! Decrements a {\tt date} by a {\tt time} and returns the
! new value of {\tt date}.
!
! !REVISION HISTORY: 
!
!  Feb 8, 2001    B. Eaton   Specification.
!
!EOP
!-------------------------------------------------------------------------

!BOP
!
! !IROUTINE:  date_diff
! 
! !INTERFACE:
!
      subroutine date_diff ( date1, date2, time, islater )

! !USES: 

!     none

! !INPUT PARAMETERS: 
!
      implicit NONE

      type(date_t), intent(in) :: date1     ! First date
      type(date_t), intent(in) :: date2     ! Second date

! !OUTPUT PARAMETERS:
!
      type(time_t), intent(out) :: time     ! Time difference
      logical, intent(out) :: islater       ! Difference flag

! !DESCRIPTION:
!
! Returns the difference ({\tt date1 - date2}) as a time interval (always positive)
! and a flag {\tt islater} which is true only if {\tt date1} is later than {\tt date2}.
!
! !REVISION HISTORY: 
!
!  Feb 8, 2001    B. Eaton   Specification.
!
!EOP
!-------------------------------------------------------------------------

!BOP
!
! !IROUTINE:  date_diff_days
! 
! !INTERFACE:
!
      function date_diff_days ( date1, date2 )

! !USES: 

!     none

! !INPUT PARAMETERS: 
!
      implicit NONE

      type(date_t), intent(in) :: date1      ! First date
      type(date_t), intent(in) :: date2      ! Second date

! !OUTPUT PARAMETERS:
!
      real(r8) :: date_diff_days        ! Returned date

! !DESCRIPTION:
!
! Returns the difference ({\tt date1 - date2}) as a floating point number of
! days.  This difference is negative if {\tt date2} is later than {\tt date1}.
!
! !REVISION HISTORY: 
!
!  Feb 8, 2001    B. Eaton   Specification.
!
!EOP
!-------------------------------------------------------------------------

!BOP
!
! !IROUTINE:  date_calendar_day
! 
! !INTERFACE:
!
      function date_calendar_day ( date )

! !USES: 

!     none

! !INPUT PARAMETERS: 
!
      implicit NONE

      type(date_t), intent(in) :: date      ! Input date

! !OUTPUT PARAMETERS:
!
      real(r8) :: calendar_day              ! Returned calendar day

! !DESCRIPTION:
!
! Returns the calendar day corresponding to {\tt date}.
!
! !REVISION HISTORY: 
!
!  Feb 8, 2001    B. Eaton   Specification.
!
!EOP
!-------------------------------------------------------------------------










